Public
Edited
Oct 16, 2024
Paused
20 forks
1 star
Insert cell
Insert cell
Insert cell
animalData = d3.csv("https://magrawala.github.io/cs448b-fa20/assets/docs/animals.csv", function(d) {
return {
// We parse the data into an array of csv objects. We could for example change the names of fields.
id: +d.id,
animal: d.animal,
weight: +d.weight,
height: +d.height,
name: d.name
};
}).then(function(animalData) {
//Outside of Observable notebooks you would put all code to draw the graph here.
return animalData;
});

Insert cell
printTable(animalData)
Insert cell
Insert cell
Insert cell
Insert cell
plotVars = (
{plotWidth: 200, //Width of plot region
plotHeight: 200, //Height of plot region
plotMargin: 50, //Margin space for axes and their labels
plotCircleRadius: 5 //Radius in pixels of circles in the plot
}
);
Insert cell
Insert cell
xScale = d3.scaleLinear()
.domain([0, 10])
.range(/* fill in */);
Insert cell
yScale = d3.scaleLinear()
.domain([0, 10])
.range(/* fill in */); //Flip y-range to deal with SVG origin at top,left
Insert cell
xScale(5)
Insert cell
Insert cell
function drawScatterPlot(animalData, plotContainer) {
plotContainer.selectAll(/* fill in */) //select all of the SVG 'circle' elements in the plotContainer
.data(/* fill in */) //bind the data, using d.id as the key
.join(
enter => enter.append(/* fill in */), //append an svg 'circle' element for each entering data item
update => update, //do nothing with data items that match existing items
exit => exit.remove() //remove svg 'circle' elements whose data is now gone.
)
.attr('r', /* fill in */) //use plotVars.plotCircleRadius
.attr('cx', /* fill in */) //base on d.weight
.attr('cy', /* fill in */) //base d.height
.attr('fill', function (d) { //set to steelblue if d.animal='cat', salmon if d.animal='dog'
return /* fill in */
})
}
Insert cell
Insert cell
{
let svgPlotContainer = d3.create('svg')
.attr('width',plotVars.plotWidth)
.attr('height',plotVars.plotHeight)
.style('background-color', 'whitesmoke'); //Color container bg to see its extent
// drawScatterPlot(animalData, svgPlotContainer);
return svgPlotContainer.node();
}
Insert cell
Insert cell
Insert cell
function createAxes(plotContainer) {

const xAxis = plotContainer.append('g') //create SVG <g> elt for x-axis
.attr('transform', `translate(0,${plotVars.plotHeight})`) //translate to bottom of plot
.call(d3.axisBottom(xScale)); //use axisBottom to form ticks below
const yAxis = plotContainer.append('g') //create SVG <g> elt for y-axis
.call(d3.axisLeft(yScale)); //use axisLeft to form ticks to the left
const xAxisLabel = plotContainer.append("text")
.attr("transform", `translate(${plotVars.plotWidth/2}, ${plotVars.plotHeight + 35})`)
.style("text-anchor", "middle")
.text("Weight");
const yAxisLabel = plotContainer.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - plotVars.plotMargin)
.attr("x",0 - (plotVars.plotHeight / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Height");
}
Insert cell
Insert cell
{
let svgPlotContainer = d3.create('svg')
.attr('width',plotVars.plotWidth)
.attr('height',plotVars.plotHeight)
.style('background-color', 'whitesmoke');
//createAxes(svgPlotContainer);
//drawScatterPlot(animalData, svgPlotContainer);

return svgPlotContainer.node()
}
Insert cell
Insert cell
Insert cell
function createWholeChartContainer() {
const outerWidth = /* fill in */; // extend plotWidth by twice plotMargin
const outerHeight = /* fill in */; // extend plotHeight by twice plotMargin
var wholeChartContainer = d3.create('svg')
.attr('width', outerWidth)
.attr('height',outerHeight)
.style('background-color', 'whitesmoke')
wholeChartContainer.append('g')
// Translate g element by plotMargin, plotMargin to place inner plotting region.
.attr('transform', `translate(${plotVars.plotMargin},${plotVars.plotMargin})`)
.attr('id', 'plotContainer'); //Give the plot container an id so we can access it later.
return wholeChartContainer;

}
Insert cell
Insert cell
{
let wholeChartContainer = createWholeChartContainer();
let plotContainer = wholeChartContainer.select('#plotContainer');
//Add rect to plotContainer of size plotWidth x plotHeight to visualize it
//plotContainer.append('rect')
//.attr('width',plotVars.plotWidth)
//.attr('height',plotVars.plotHeight)
//.attr('fill','burlywood');
return wholeChartContainer.node();
}
Insert cell
Insert cell
{
let wholeChartContainer = createWholeChartContainer();
let plotContainer = wholeChartContainer.select('#plotContainer');
//createAxes(plotContainer);
//drawScatterPlot(animalData, plotContainer);

return wholeChartContainer.node()
}
Insert cell
Insert cell
function drawScatterPlotMO(animalData, plotContainer) {
plotContainer.selectAll('circle')
.data(animalData, d=>d.id)
.join('circle')
//Set attributes for entering and updating elements
.attr('r',plotVars.plotCircleRadius)
.attr('cx',function(d){ return xScale(d.weight); })
.attr('cy',function(d){ return yScale(d.height); })
.attr('fill', function (d) {
return d.animal === 'cat' ? 'steelblue' : 'salmon'
})
.on('mouseover', function (event, d) { //Handle 'mouseover' events
plotContainer.append(/* fill in */) //Append SVG 'text' element.
.attr('class', /* fill in */) //Set class to 'ptLabel' so can remove easily later
.attr('x', /* fill in */) //Set label position near its circle xScale(d.weight)
.attr('y', /* fill in */) //Set label position near its circle yScale(d.height)
.text(d.name);
})
.on('mouseout', function(event, d) {
plotContainer.selectAll(/* fill in */).remove() // Remove all ptLabels
});
}
Insert cell
{
let wholeChartContainer = createWholeChartContainer();
let plotContainer = wholeChartContainer.select('#plotContainer');
//createAxes(plotContainer);
//drawScatterPlotMO(animalData, plotContainer);

return wholeChartContainer.node()
}
Insert cell
Insert cell
html`
<html>
<head>
</head>
<body>
<h2>Height vs. Weight for Cats & Dogs</h2>
<span> Filter Buttons: </span>
<button id='cats-only' data-filter='cat' style='background-color: steelblue'>
Cats Only
</button>
<button id='dogs-only' data-filter='dog' style='background-color: salmon'>
Dogs Only
</button>
<button id='both' data-filter='both' style='background-color: gray'>
Both
</button>
<div id ="animal-vis"></div>
</body>
</html>
`
Insert cell
Insert cell
function handleButtons(animalData, plotContainer) {
let buttons = d3.selectAll('button');
buttons.on('click', function() { // Add 'click' event listeners and handlers
// In function working with D3 selection, 'this' refers to the current DOM node
let chosenAnimal = this.dataset.filter; //Value of the 'data-filter' attr of the button.
let newData = animalData;
if (chosenAnimal !== 'both') {
newData = animalData.filter(d => d.animal === chosenAnimal);
}
drawScatterPlotMO(newData, plotContainer);
});
}
Insert cell
Insert cell
{
let wholeChartContainer = createWholeChartContainer();
let plotContainer = wholeChartContainer.select('#plotContainer');

//createAxes(plotContainer);
//drawScatterPlotMO(animalData, plotContainer);
//handleButtons(animalData,plotContainer);
//Attach the node we created using d3.create() to the part of the DOM we setup using HTML above.
d3.select('#animal-vis').selectAll("*").remove(); //Remove any plots that may already have been created.
d3.select('#animal-vis').append( () => /* fill in */); //Attach wholeChartContainer.node() to DOM;
}

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
d3 = require('d3@7')
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more